#ifndef __ANSI_H
#define __ANSI_H

/* whether it is printable character */
#define ANSI_ISCHAR(ch) (ch >= 0x20 && ch < 0x7f)
/* whether it is number character */
#define ANSI_ISNUMBER(ch) (ch > 0x2f && ch < 0x3a)
/* whether it is uppercase alphabet */
#define ANSI_ISUPCASE(ch) (ch > 0x40 && ch < 0x5b)
/* whether it is lowercase alphabet */
#define ANSI_ISLOWCASE(ch) (ch > 0x60 && ch < 0x7b)
/* whether it is alphabet */
#define ANSI_ISALPHA(ch) ((ch > 0x40 && ch < 0x5b) || (ch > 0x60 && ch < 0x7b))
/* is ctrl0 code */
#define ANSI_ISCTRL0(ch) (ch >= 0x00 && ch < 0x80)
/* is ctrl1 code */
#define ANSI_ISCTRL1(ch) (ch > 0x7f && ch < 0xa0)

/// ANSI control0 code (CO table) table, [0x00, 0x7f]
/*      abbr.                                          oct  dec  hex     escap   desc */
#define _ANSI_C0_NUT            '\x00'              /* 00   0    0x00    \0      null */
#define _ANSI_C0_SOH            '\x01'              /* 00   0    0x01    xx      start of headline */
#define _ANSI_C0_STX            '\x02'              /* 00   0    0x02    xx      start of text */
#define _ANSI_C0_ETX            '\x03'              /* 00   0    0x03    xx      end of text */
#define _ANSI_C0_EOT            '\x04'              /* 00   0    0x04    xx      end of transmission */
#define _ANSI_C0_ENQ            '\x05'              /* 00   0    0x05    xx      enquiry */
#define _ANSI_C0_ACK            '\x06'              /* 00   0    0x06    xx      acknowledge */
#define _ANSI_C0_BEL            '\x07'              /* 00   0    0x07    xx      bell */
#define _ANSI_C0_BS             '\x08'              /* 00   0    0x08    \b      backspace */
#define _ANSI_C0_HT             '\x09'              /* 00   0    0x09    xx      horizontal tab */
#define _ANSI_C0_LF             '\x0A'              /* 00   0    0x0A    xx      line feed, NL(new line) */
#define _ANSI_C0_VT             '\x0B'              /* 00   0    0x0B    xx      vertical tab */
#define _ANSI_C0_FF             '\x0C'              /* 00   0    0x0C    xx      form feed, NP(new page) */
#define _ANSI_C0_CR             '\x0D'              /* 00   0    0x0D    xx      carriage return */
#define _ANSI_C0_SO             '\x0E'              /* 00   0    0x0E    xx      shift out */
#define _ANSI_C0_SI             '\x0F'              /* 00   0    0x0F    xx      shift in */
#define _ANSI_C0_DLE            '\x10'              /* 00   0    0x10    xx      data link escape */
#define _ANSI_C0_DCI            '\x11'              /* 00   0    0x11    xx      device control 1 */
#define _ANSI_C0_DC2            '\x12'              /* 00   0    0x12    xx      device control 2 */
#define _ANSI_C0_DC3            '\x13'              /* 00   0    0x13    xx      device control 3 */
#define _ANSI_C0_DC4            '\x14'              /* 00   0    0x14    xx      device control 4 */
#define _ANSI_C0_NAK            '\x15'              /* 00   0    0x15    xx      negative acknowledge */
#define _ANSI_C0_SYN            '\x16'              /* 00   0    0x16    xx      synchronous idle */
#define _ANSI_C0_TB             '\x17'              /* 00   0    0x17    xx      end of trans. block */
#define _ANSI_C0_CAN            '\x18'              /* 00   0    0x18    xx      cancel */
#define _ANSI_C0_EM             '\x19'              /* 00   0    0x19    xx      end of medium */
#define _ANSI_C0_SUB            '\x1A'              /* 00   0    0x1A    xx      substitute */
#define _ANSI_C0_ESC            '\x1B'              /* 00   0    0x1B    \e      escape */
#define _ANSI_C0_FS             '\x1C'              /* 00   0    0x1C    xx      file separator */
#define _ANSI_C0_GS             '\x1D'              /* 00   0    0x1D    xx      group separator */
#define _ANSI_C0_RS             '\x1E'              /* 00   0    0x1E    xx      record separator */
#define _ANSI_C0_US             '\x1F'              /* 00   0    0x1F    xx      unit separator */
#define _ANSI_C0_DEL            '\x7F'              /* 00   0    0x7F    xx      delete */
/* define to string for macro joint */
#define ANSI_C0_NUT             "\x00"
#define ANSI_C0_SOH             "\x01"
#define ANSI_C0_STX             "\x02"
#define ANSI_C0_ETX             "\x03"
#define ANSI_C0_EOT             "\x04"
#define ANSI_C0_ENQ             "\x05"
#define ANSI_C0_ACK             "\x06"
#define ANSI_C0_BEL             "\x07"
#define ANSI_C0_BS              "\x08"
#define ANSI_C0_HT              "\x09"
#define ANSI_C0_LF              "\x0A"
#define ANSI_C0_VT              "\x0B"
#define ANSI_C0_FF              "\x0C"
#define ANSI_C0_CR              "\x0D"
#define ANSI_C0_SO              "\x0E"
#define ANSI_C0_SI              "\x0F"
#define ANSI_C0_DLE             "\x10"
#define ANSI_C0_DCI             "\x11"
#define ANSI_C0_DC2             "\x12"
#define ANSI_C0_DC3             "\x13"
#define ANSI_C0_DC4             "\x14"
#define ANSI_C0_NAK             "\x15"
#define ANSI_C0_SYN             "\x16"
#define ANSI_C0_TB              "\x17"
#define ANSI_C0_CAN             "\x18"
#define ANSI_C0_EM              "\x19"
#define ANSI_C0_SUB             "\x1A"
#define ANSI_C0_ESC             "\x1B"
#define ANSI_C0_FS              "\x1C"
#define ANSI_C0_GS              "\x1D"
#define ANSI_C0_RS              "\x1E"
#define ANSI_C0_US              "\x1F"
#define ANSI_C0_DEL             "\x7F"
/* escape sequence, start with `ANSI_C0_ESC` */
#define ANSI_C0_RIS             ANSI_C0_ESC"c"      /* Reset to Initial State */
#define ANSI_C0_SS2             ANSI_C0_ESC"N"      /* Single Shift Two, equivalent C1(0x8E) */
#define ANSI_C0_SS3             ANSI_C0_ESC"O"      /* Single Shift Three, equivalent C1(0x8F) */
#define ANSI_C0_DCS             ANSI_C0_ESC"P"      /* Device Control String, equivalent C1(0x90) */
#define ANSI_C0_CSI             ANSI_C0_ESC"["      /* Control Sequence Introducer, equivalent C1(0x9B) */
#define ANSI_C0_ST              ANSI_C0_ESC"\\"     /* String Terminator, equivalent C1(0x9C) */
#define ANSI_C0_OSC             ANSI_C0_ESC"]"      /* Operating System Command, equivalent C1(0x9D) */
#define ANSI_C0_SOS             ANSI_C0_ESC"X"      /* Start of String, equivalent C1(0x98) */
#define ANSI_C0_PM              ANSI_C0_ESC"^"      /* Privacy Message, equivalent C1(0x9E) */
#define ANSI_C0_APC             ANSI_C0_ESC"_"      /* Application Program Command, equivalent C1(0x9F) */

/// ANSI control1 code (C1 table) table, [0x80, 0x9F]
/* western european characters or c1 control characters, some commands are equivalent to escape sequence */
#define _ANSI_C1_PAD            '\x80'              /* (€), Padding Character */
#define _ANSI_C1_HOP            '\x81'              /* ( ), High Octet Preset */
#define _ANSI_C1_BPH            '\x82'              /* (‚), Break Permitted Here */
#define _ANSI_C1_NBH            '\x83'              /* (ƒ), No Break Here */
#define _ANSI_C1_IND            '\x84'              /* („), Index */
#define _ANSI_C1_NEL            '\x85'              /* (…), Next Line */
#define _ANSI_C1_SSA            '\x86'              /* (†), Start of Selected Area */
#define _ANSI_C1_ESA            '\x87'              /* (‡), End of Selected Area */
#define _ANSI_C1_HTS            '\x88'              /* (ˆ), Character Tabulation Set */
#define _ANSI_C1_HTJ            '\x89'              /* (‰), Character Tabulation with Justification */
#define _ANSI_C1_VTS            '\x8A'              /* (Š), Line Tabulation Set */
#define _ANSI_C1_PLD            '\x8B'              /* (‹), Partial Line Down */
#define _ANSI_C1_PLU            '\x8C'              /* (Œ), Partial Line Up */
#define _ANSI_C1_RI             '\x8D'              /* ( ), Reverse Index */
#define _ANSI_C1_SS2            '\x8E'              /* (Ž), Single Shift Two */
#define _ANSI_C1_SS3            '\x8F'              /* ( ), Single Shift Three */
#define _ANSI_C1_DCS            '\x90'              /* ( ), Device Control String */
#define _ANSI_C1_PU1            '\x91'              /* (‘), Private Use 1 */
#define _ANSI_C1_PU2            '\x92'              /* (’), Private Use 2 */
#define _ANSI_C1_STS            '\x93'              /* (“), Set Transmit State */
#define _ANSI_C1_CCH            '\x94'              /* (”), Cancel Character */
#define _ANSI_C1_MW             '\x95'              /* (•), Message Waiting */
#define _ANSI_C1_SPA            '\x96'              /* (–), Start of Protected Area */
#define _ANSI_C1_EPA            '\x97'              /* (—), End of Protected Area */
#define _ANSI_C1_SOS            '\x98'              /* (˜), Start of String */
#define _ANSI_C1_SGC            '\x99'              /* (™), Single Graphic Character Introducer */
#define _ANSI_C1_SCI            '\x9A'              /* (š), Single Character Introducer */
#define _ANSI_C1_CSI            '\x9B'              /* (›), Control Sequence Introducer */
#define _ANSI_C1_ST             '\x9C'              /* (œ), String Terminator */
#define _ANSI_C1_OSC            '\x9D'              /* ( ), Operating System Command */
#define _ANSI_C1_PM             '\x9E'              /* (ž), Privacy Message */
#define _ANSI_C1_APC            '\x9F'              /* (Ÿ), Application Program Command */
/* define to string for macro joint */
#define ANSI_C1_PAD             "\x80"
#define ANSI_C1_HOP             "\x81"
#define ANSI_C1_BPH             "\x82"
#define ANSI_C1_NBH             "\x83"
#define ANSI_C1_IND             "\x84"
#define ANSI_C1_NEL             "\x85"
#define ANSI_C1_SSA             "\x86"
#define ANSI_C1_ESA             "\x87"
#define ANSI_C1_HTS             "\x88"
#define ANSI_C1_HTJ             "\x89"
#define ANSI_C1_VTS             "\x8A"
#define ANSI_C1_PLD             "\x8B"
#define ANSI_C1_PLU             "\x8C"
#define ANSI_C1_RI              "\x8D"
#define ANSI_C1_SS2             "\x8E"
#define ANSI_C1_SS3             "\x8F"
#define ANSI_C1_DCS             "\x90"
#define ANSI_C1_PU1             "\x91"
#define ANSI_C1_PU2             "\x92"
#define ANSI_C1_STS             "\x93"
#define ANSI_C1_CCH             "\x94"
#define ANSI_C1_MW              "\x95"
#define ANSI_C1_SPA             "\x96"
#define ANSI_C1_EPA             "\x97"
#define ANSI_C1_SOS             "\x98"
#define ANSI_C1_SGC             "\x99"
#define ANSI_C1_SCI             "\x9A"
#define ANSI_C1_CSI             "\x9B"
#define ANSI_C1_ST              "\x9C"
#define ANSI_C1_OSC             "\x9D"
#define ANSI_C1_PM              "\x9E"
#define ANSI_C1_APC             "\x9F"

/// CSI (Control Sequence Introducer) sequences
#define __ANSI_CSI_CUU(n)       ANSI_C0_CSI#n"A"        /* Cursor Up */
#define __ANSI_CSI_CUD(n)       ANSI_C0_CSI#n"B"        /* Cursor Down */
#define __ANSI_CSI_CUF(n)       ANSI_C0_CSI#n"C"        /* Cursor Forward */
#define __ANSI_CSI_CUB(n)       ANSI_C0_CSI#n"D"        /* Cursor Back */
#define __ANSI_CSI_CNL(n)       ANSI_C0_CSI#n"E"        /* Cursor Next Line */
#define __ANSI_CSI_CPL(n)       ANSI_C0_CSI#n"F"        /* Cursor Previous Line */
#define __ANSI_CSI_CHA(n)       ANSI_C0_CSI#n"G"        /* Cursor Horizontal Absolute */
#define __ANSI_CSI_CUP(x, y)    ANSI_C0_CSI#x";"#y"H"   /* Cursor Position */
#define __ANSI_CSI_ED(n)        ANSI_C0_CSI#n"J"        /* Erase in Display, 0=erase all front, 1=erase all back, 2=rease all screen */
#define __ANSI_CSI_EL(n)        ANSI_C0_CSI#n"K"        /* Erase in Line */
#define __ANSI_CSI_SU(n)        ANSI_C0_CSI#n"S"        /* Scroll Up */
#define __ANSI_CSI_SD(n)        ANSI_C0_CSI#n"T"        /* Scroll Down */
#define __ANSI_CSI_HVP(n, m)    ANSI_C0_CSI#n";"#m"H"   /* Vertical Position */
#define __ANSI_CSI_DCH(n)       ANSI_C0_CSI#n"P"        /* delete preceding charactor */
#define __ANSI_CSI_SGR(n)       ANSI_C0_CSI#n"m"        /* Select Graphic Rendition */
#define ANSI_CSI_AUXON          ANSI_C0_CSI"5i"         /* Port On */
#define ANSI_CSI_AUXOFF         ANSI_C0_CSI"4i"         /* Port Off */
#define ANSI_CSI_IME            ANSI_C0_CSI"4h"         /* insert mode enable, NOTE: custom name */
#define ANSI_CSI_IMD            ANSI_C0_CSI"4l"         /* insert mode disable, NOTE: custom name */
#define ANSI_CSI_DSR            ANSI_C0_CSI"6n"         /* Device Status Report (Get cursor position) */
#define ANSI_CSI_SCP            ANSI_C0_CSI"s"          /* Save Current Cursor Position */
#define ANSI_CSI_RCP            ANSI_C0_CSI"u"          /* Restore Saved Cursor Position */
                                                        /* ...... */
/* solve the problem of macro not expanding */
#define ANSI_CSI_CUU(n)         __ANSI_CSI_CUU(n)
#define ANSI_CSI_CUD(n)         __ANSI_CSI_CUD(n)
#define ANSI_CSI_CUF(n)         __ANSI_CSI_CUF(n)
#define ANSI_CSI_CUB(n)         __ANSI_CSI_CUB(n)
#define ANSI_CSI_CNL(n)         __ANSI_CSI_CNL(n)
#define ANSI_CSI_CPL(n)         __ANSI_CSI_CPL(n)
#define ANSI_CSI_CHA(n)         __ANSI_CSI_CHA(n)
#define ANSI_CSI_CUP(x, y)      __ANSI_CSI_CUP(x, y)
#define ANSI_CSI_ED(n)          __ANSI_CSI_ED(n)
#define ANSI_CSI_EL(n)          __ANSI_CSI_EL(n)
#define ANSI_CSI_SU(n)          __ANSI_CSI_SU(n)
#define ANSI_CSI_SD(n)          __ANSI_CSI_SD(n)
#define ANSI_CSI_HVP(n, m)      __ANSI_CSI_HVP(n, m)
#define ANSI_CSI_DCH(n)         __ANSI_CSI_DCH(n)
#define ANSI_CSI_SGR(n)         __ANSI_CSI_SGR(n)

/* CSI-SGR (Select Graphic Rendition) parameters,
   from 0 ~ 107, see the table [SGR (Select Graphic Rendition) parameters]
   local path: document/specifications/ANSI escape code.pdf */
/* CSI-SGR colors */
#define Black                   0
#define Red                     1
#define Green                   2
#define Yellow                  3
#define Blue                    4
#define Magenta                 5
#define Cyan                    6
#define White                   7
#define BrightBlack             0
#define BrightRed               1
#define BrightGreen             2
#define BrightYellow            3
#define BrightBlue              4
#define BrightMagenta           5
#define BrightCyan              6
#define BrightWhite             7
/* CSI-SGR color base macro */
#define ANSI_SGR_RGB8(n)        5;n
#define ANSI_SGR_RGB24(r, g, b) 2;r;g;b
/* CSI-SGR color front and background macro */
#define __ansi_sgr_fcolor4(c)           ANSI_CSI_SGR(3##c)                          // 4-bit foreground color, 0 ≤ c ≤ 7
#define __ansi_sgr_fcolor4b(c)          ANSI_CSI_SGR(9##c)                          // 4-bit background color, 0 ≤ c ≤ 7
#define __ansi_sgr_bcolor4(b)           ANSI_CSI_SGR(4##b)                          // 4-bit foreground bright color, 0 ≤ b ≤ 7
#define __ansi_sgr_bcolor4b(b)          ANSI_CSI_SGR(10##b)                         // 4-bit background bright color, 0 ≤ b ≤ 7
#define __ansi_sgr_fcolor8(n)           ANSI_CSI_SGR(38;ANSI_SGR_RGB8(n))           // 8-bit foreground color, 0 ≤ c ≤ 255 (when c in [231:16], the formulas is `c = 16+36*r+6*g+b (0 ≤ r, g, b ≤ 5)`)
#define __ansi_sgr_bcolor8(n)           ANSI_CSI_SGR(48;ANSI_SGR_RGB8(n))           // 8-bit background color, 0 ≤ c ≤ 255 (when c in [231:16], the formulas is `c = 16+36*r+6*g+b (0 ≤ r, g, b ≤ 5)`)
#define __ansi_sgr_ucolor8(n)           ANSI_CSI_SGR(58;ANSI_SGR_RGB8(n))           // 8-bit underline color, 0 ≤ c ≤ 255 (when c in [231:16], the formulas is `c = 16+36*r+6*g+b (0 ≤ r, g, b ≤ 5)`)
#define __ansi_sgr_fcolor24(r, g, b)    ANSI_CSI_SGR(38;ANSI_SGR_RGB24(r, g, b))    // 24-bit foreground color, 0 ≤ r|g|b ≤ 255
#define __ansi_sgr_bcolor24(r, g, b)    ANSI_CSI_SGR(48;ANSI_SGR_RGB24(r, g, b))    // 24-bit background color, 0 ≤ r|g|b ≤ 255
#define __ansi_sgr_ucolor24(r, g, b)    ANSI_CSI_SGR(58;ANSI_SGR_RGB24(r, g, b))    // 24-bit underline color, 0 ≤ r|g|b ≤ 255
/* solve the problem of macro not expanding */
#define ansi_sgr_fcolor4(c)             __ansi_sgr_fcolor4(c)
#define ansi_sgr_fcolor4b(c)            __ansi_sgr_fcolor4b(c)
#define ansi_sgr_bcolor4(b)             __ansi_sgr_bcolor4(b)
#define ansi_sgr_bcolor4b(b)            __ansi_sgr_bcolor4b(b)
#define ansi_sgr_fcolor8(n)             __ansi_sgr_fcolor8(n)
#define ansi_sgr_bcolor8(n)             __ansi_sgr_bcolor8(n)
#define ansi_sgr_ucolor8(n)             __ansi_sgr_ucolor8(n)
#define ansi_sgr_fcolor24(r, g, b)      __ansi_sgr_fcolor24(r, g, b)
#define ansi_sgr_bcolor24(r, g, b)      __ansi_sgr_bcolor24(r, g, b)
#define ansi_sgr_ucolor24(r, g, b)      __ansi_sgr_ucolor24(r, g, b)

#endif
